﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Drawing;
using System.Runtime.InteropServices;

using DNA;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Application = Autodesk.AutoCAD.ApplicationServices.Application;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.EditorInput;
using TJADRICD.CollaborativeDesignPlugin;

namespace TJADRICD.CollaborativeDesignPlugin.Function
{
    public static class Function_Hash
    {
        

        public static String FormatedMD5(UInt32 A,UInt32 B,UInt32 C,UInt32 D)
        {
            String value = "";
            Char[] array = new Char[32];

            for (int i = 0; i < 32; ++i) 
            {
                array[i] = '0';
            }

            value = Convert.ToString(A, 16);
            value.CopyTo(0, array, 8 - value.Length, value.Length);

            value = Convert.ToString(B, 16);
            value.CopyTo(0, array, 16 - value.Length, value.Length);

            value = Convert.ToString(C, 16);
            value.CopyTo(0, array, 24 - value.Length, value.Length);

            value = Convert.ToString(D, 16);
            value.CopyTo(0, array, 32 - value.Length, value.Length);

            value = new String(array);

            return value;
        }

        //获得Database中的所有MD5码
        public static String GetDwgHash(Database dbToHash)
        {
            string strHashCode = null;

            UInt32 A = 0;
            UInt32 B = 0;
            UInt32 C = 0;
            UInt32 D = 0;
            

            Database db = dbToHash;
            Transaction ta = db.TransactionManager.StartTransaction();
            BlockTable bt = (BlockTable)ta.GetObject(db.BlockTableId, OpenMode.ForRead);
            BlockTableRecord btr = (BlockTableRecord)ta.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);

            String Temp = null;
            foreach (ObjectId objectid in btr)
            {
                try
                {
                    Entity ent = (Entity)ta.GetObject(objectid, OpenMode.ForRead, true);
                    if (ent is BlockReference)
                    {
                        BlockReference br = ent as BlockReference;
                        BlockTableRecord btr2 = ta.GetObject(br.BlockTableRecord, OpenMode.ForRead) as BlockTableRecord;
                        Temp = "Fail Geo" + " Name=" + br.Name + " BlockName=" + ent.BlockName;
                        if (btr2.Name.StartsWith("sign_"))
                        {
                            continue;
                        }
                    }
                    UInt32 a = 0;
                    UInt32 b = 0;
                    UInt32 c = 0;
                    UInt32 d = 0;
                    GetSingleMD5(ent, ref a, ref b, ref c, ref d);      
                    A = A ^ a;
                    B = B ^ b;
                    C = C ^ c;
                    D = D ^ d;
                }
                catch
                {

                }
            }
            strHashCode = FormatedMD5(A, B, C, D);

            ta.Commit();
            return strHashCode;
        }

        //输入名字，获得该名字对应的MD5码
        public static String GetNameMD5(String strName)
        {
            StringBuilder name = new StringBuilder(strName);
            UInt32 A = 0;
            UInt32 B = 0;
            UInt32 C = 0;
            UInt32 D = 0;
            Extern.MD5_Data_I(name, ref A, ref  B, ref C, ref D, name.Length);
            
            String strNameMD5 = FormatedMD5(A, B, C, D);
            
            return strNameMD5;
        }

        public static String GetSingleMD5(Entity ent,ref UInt32 A,ref UInt32 B,ref UInt32 C,ref UInt32 D)
        {
            StringBuilder message = new StringBuilder("");
            StringBuilder message2 = new StringBuilder("");
            StringBuilder message3 = new StringBuilder("");


            UInt32 a = 0;
            UInt32 b = 0;
            UInt32 c = 0;
            UInt32 d = 0;

            bool is_text = false;

            bool flag = true;
            try
            {
                DBText dt = ent as DBText;
                message2.Append(dt.TextString);
            }
            catch
            {
                flag = false;
            }
            if (flag)
            {
                message.Append(message2.ToString());
                is_text = true;
            }

            flag = true;
            try
            {
                MText dt = ent as MText;
                message3.Append(dt.Text);
            }
            catch
            {
                flag = false;
            }
            if (flag)
            {
                message.Append(message3.ToString());
                is_text = true;
            }
            
            if (!is_text)
            {
                if (ent is BlockReference)
                {
                    try
                    {
                        BlockReference br = ent as BlockReference;
                        message.Append(br.GeometryExtentsBestFit().ToString());


                    }
                    catch
                    {
                        ;
                    }
                }
                else
                {
                        message.Append(ent.GeometricExtents.ToString());
                }
            }
            

            Int32 length = message.Length;
            Extern.MD5_Data_I(message, ref a, ref b, ref c, ref d, length);
            A = a;
            B = b;
            C = c;
            D = d;
            

            return message.ToString();
        }

        public static String GetSingleMD5String(Entity ent)
        {
            UInt32 A = 0;
            UInt32 B = 0;
            UInt32 C = 0;
            UInt32 D = 0;

            return GetSingleMD5(ent, ref A, ref B, ref C, ref D);
        }
    }
}
